package com.onlyxiahui.common.utils.base.security.asymmetric;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.interfaces.RSAKey;

import javax.crypto.Cipher;

import com.onlyxiahui.common.utils.base.security.Base64Util;
import com.onlyxiahui.common.utils.base.security.CipherUtil;

/**
 * 
 * 
 * linux版openssl生成rsa公私钥 不指定为2048
 * 
 * 1、生成私钥 *.pem文件放在当前文件夹下<br>
 * openssl genrsa -out rsa_private_key.pem 1024
 * 
 * 2、对私钥进行PKCS#8编码<br>
 * openssl pkcs8 -topk8 -in rsa_private_key.pem -out rsa_private_key_pkcs8.pem
 * -nocrypt
 * 
 * 3、根据生成的私钥生成公钥<br>
 * openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout
 * 
 * 
 * 
 * Description <br>
 * Date 2020-11-09 11:30:56<br>
 * 
 * @author XiaHui [onlovexiahui@qq.com]<br>
 * @since 1.0.0
 */

public class SecurityRsaUtil {

	public static String encryptToBase64String(String text, Key key) {
		byte[] bytes = encrypt(text, key);
		return null != bytes ? Base64Util.encrypt(bytes) : null;
	}

	public static byte[] encrypt(String text, Key key) {
		byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
		return null != bytes ? encrypt(bytes, key) : null;
	}

	/**
	 * 
	 * Description 加密<br>
	 * Date 2020-11-09 13:46:01<br>
	 * 
	 * @param bytes
	 * @param key
	 * @return
	 * @since 1.0.0
	 */
	public static byte[] encrypt(byte[] bytes, Key key) {
		byte[] valueBytes = null;
		try {
			Cipher cipher = CipherUtil.getCipher(Cipher.ENCRYPT_MODE, key);
			// int blockSize = cipher.getBlockSize();
			// 加密数据长度 <= 模长-11
			int blockSize = ((RSAKey) key).getModulus().bitLength() / 8 - 11;
			// 模长
			final int dataLength = bytes.length;
			// 对数据解密
			// 不足分段
			if (dataLength <= blockSize) {
				valueBytes = cipher.doFinal(bytes, 0, dataLength);
			} else {
				valueBytes = CipherUtil.doFinalWithBlock(cipher, bytes, blockSize);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
//		byte[] valueBytes = null;
//		try {
//			KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//			// 对数据加密
//			Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
//			cipher.init(Cipher.ENCRYPT_MODE, key);
//			ByteArrayOutputStream out = new ByteArrayOutputStream();
//			int length = bytes.length;
//			int offSet = 0;
//			byte[] cache;
//			int i = 0;
//			// 对数据分段加密
//			while (length - offSet > 0) {
//				if (length - offSet > MAX_ENCRYPT_BLOCK) {
//					cache = cipher.doFinal(bytes, offSet, MAX_ENCRYPT_BLOCK);
//				} else {
//					cache = cipher.doFinal(bytes, offSet, length - offSet);
//				}
//				out.write(cache, 0, cache.length);
//				i++;
//				offSet = i * MAX_ENCRYPT_BLOCK;
//			}
//			valueBytes = out.toByteArray();
//			out.close();
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		return valueBytes;
	}

	public static String decryptByBase64String(String text, Key key) {
		// 获得待解密数据
		byte[] bytes = Base64Util.decrypt(text);
		byte[] valueBytes = decrypt(bytes, key);
		return null != valueBytes ? new String(valueBytes, StandardCharsets.UTF_8) : null;
	}

	/**
	 * 
	 * Description 解密<br>
	 * Date 2020-11-09 13:46:17<br>
	 * 
	 * @param bytes
	 * @param key
	 * @return
	 * @since 1.0.0
	 */
	public static byte[] decrypt(byte[] bytes, Key key) {
		byte[] valueBytes = null;
		try {
			// , int keyLength
			Cipher cipher = CipherUtil.getCipher(Cipher.DECRYPT_MODE, key);
			// final int blockSize = cipher.getBlockSize();
			int blockSize = ((RSAKey) key).getModulus().bitLength() / 8;
			// 模长
			final int dataLength = bytes.length;
			// 对数据解密
			// 不足分段
			if (dataLength <= blockSize) {
				valueBytes = cipher.doFinal(bytes, 0, dataLength);
			} else {
				valueBytes = CipherUtil.doFinalWithBlock(cipher, bytes, blockSize);
			}

//			ByteArrayOutputStream out = new ByteArrayOutputStream();
//			int length = bytes.length;
//
//			int offSet = 0;
//			byte[] cache;
//			int i = 0;
//			// 对数据分段解密
//			while (length - offSet > 0) {
//				if (length - offSet > MAX_DECRYPT_BLOCK) {
//					cache = cipher.doFinal(bytes, offSet, MAX_DECRYPT_BLOCK);
//				} else {
//					cache = cipher.doFinal(bytes, offSet, length - offSet);
//				}
//				out.write(cache, 0, cache.length);
//				i++;
//				offSet = i * MAX_DECRYPT_BLOCK;
//			}
//			valueBytes = out.toByteArray();
//			out.close();

		} catch (Exception e) {
			e.printStackTrace();
		}
		return valueBytes;
	}
}
